package references

import (
	"jvm/nzpJvm/instructions/base"
	"jvm/nzpJvm/runtime_area"
	"jvm/nzpJvm/runtime_area/heap"
)
// index代表一个常量池索引，此位置上是一个字段的符号引用
// 用于设置实例变量的指令
type PUT_FIELD struct{ base.Index16Instruction }

func (self *PUT_FIELD) Execute(frame *runtime_area.Frame) {
	// 获取当前类的运行时常量池
	currentMethod := frame.Method()
	currentClass := currentMethod.Class()
	constantPool := currentClass.ConstantPool()
	// 从常量池获取字段的符号引用
	fieldRef := constantPool.GetConstant(self.Index).(*heap.FieldRef)
	// 根据符号引用获取直接引用
	field := fieldRef.ResolveField()
	// 这个字段所属的类
	class := field.Class()

	// 如果这个字段是静态字段，抛出异常
	if field.IsStatic() {
		panic("java.lang.IncompatibleClassChangeError")
	}

	if field.IsFinal() {
		if field.IsFinal() {
			// 非静态的 final 字段只允许实例初始化方法进行赋值
			if currentClass != class || currentMethod.Name() != "<init>" {
				panic("java.lang.IllegalAccessError")
			}
		}
	}
	descriptor:= field.Descriptor()
	slotId := field.SlotId()
	stack := frame.OperandStack()
	switch descriptor[0] {
	case 'Z', 'B', 'C', 'S', 'I':
		// boolean，byte，char，short，int都当做int来处理
		val := stack.PopInt()
		object := stack.PopRef()
		if object == nil {
			panic("java.lang.NullPointerException")
		}
		fields := object.Fields()
		fields.SetInt(slotId,val)
	case 'J':
		// long
		val := stack.PopLong()
		object := stack.PopRef()
		if object == nil {
			panic("java.lang.NullPointerException")
		}
		fields := object.Fields()
		fields.SetLong(slotId,val)
	case 'F':
		// float
		val := stack.PopFloat()
		object := stack.PopRef()
		if object == nil {
			panic("java.lang.NullPointerException")
		}
		fields := object.Fields()
		fields.SetFloat(slotId,val)
	case 'D':
		// double
		val := stack.PopDouble()
		object := stack.PopRef()
		if object == nil {
			panic("java.lang.NullPointerException")
		}
		fields := object.Fields()
		fields.SetDouble(slotId,val)
	case 'L','[':
		// 引用类型
		val := stack.PopRef()
		object := stack.PopRef()
		if object == nil {
			panic("java.lang.NullPointerException")
		}
		fields := object.Fields()
		fields.SetRef(slotId,val)
	}
}
